package misc;
import org.apache.xmlbeans.SchemaGlobalElement;
import org.apache.xmlbeans.SchemaTypeLoader;
import org.apache.xmlbeans.XmlBeans;
import org.apache.xmlbeans.XmlErrorCodes;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.impl.common.XmlErrorWatcher;
import org.apache.xmlbeans.impl.schema.StscState;
import org.apache.xmlbeans.impl.xb.substwsdl.DefinitionsDocument;
import org.apache.xmlbeans.impl.xb.xsdschema.SchemaDocument;
import org.apache.xmlbeans.impl.xb.xsdschema.impl.SchemaDocumentImpl;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;

import javax.xml.namespace.QName;

/**
 * Fetch WSDL from DE, parse for the data types,
 * generate GWT versions of those datatypes.
 * 
 * Generate Gwt Service classes to invoke Stubs on behalf of Gwt.
 * 
 * Also generate a Mapper class for 
 * translating between Gwt Datatypes and the Axis datatypes
 * 
 * 
 * 
 * 
 * @author tchau@google.com (Your Name Here)
 *
 */
public class GwtTypeGenerator {

  private static class MyResolver
  implements org.xml.sax.EntityResolver
{
  public org.xml.sax.InputSource resolveEntity(String publicId,
                                               String systemId)
  {
     System.out.println("System ID: " + systemId);
     return null;
  }
}

  
  public static void main(String[] args) {
    
    
    // Grab WSDL, parse.
    
    
    // Generate GWT data types with getters and setters
    
    
    // Generate Mapper for bidrectional GWT-Axis datatypes.
    
    
    // Generate GWT ServiceImpl classes that translate calls into
    // calls to Stubs on behalf of GWT app.

    String wsdlFileName = "/home/tchau/workspace/SoapGwtIntegrator/src/SiteService.wsdl";
    boolean doNotValidateContents = false;
    XmlObject wsdlDoc = null;
    MyResolver entityResolver = new MyResolver();
    ArrayList outerErrorListener = new ArrayList();
    XmlErrorWatcher errorListener =
       new XmlErrorWatcher(outerErrorListener);
    ArrayList scontentlist = new ArrayList();

    try
    {
       SchemaTypeLoader loader =
          XmlBeans.typeLoaderForClassLoader(
             SchemaDocument.class.getClassLoader());

       XmlOptions options = new XmlOptions();
       options.setLoadLineNumbers();
       options.setLoadSubstituteNamespaces(
          Collections.singletonMap("http://schemas.xmlsoap.org/wsdl/",
                  "http://www.apache.org/internal/xmlbeans/wsdlsubst"));
       options.setEntityResolver(entityResolver);

       System.out.println("Parsing WSDL: " + wsdlFileName + "...");

       wsdlDoc = loader.parse(new File(wsdlFileName), null, options);
       
       if (!(wsdlDoc instanceof DefinitionsDocument))
       {
          // Create new definitions doc
          DefinitionsDocument.Definitions definitions =
             DefinitionsDocument.Definitions.Factory.newInstance();

          // Set types array
          definitions.setTypesArray(wsdlDoc.selectPath("wsdl:types"));
          DefinitionsDocument defDoc =
             DefinitionsDocument.Factory.newInstance();
          defDoc.setDefinitions(definitions);

          // Adding constructed schema
          addWsdlSchemas(wsdlFileName,
                         defDoc,
                         errorListener,
                         doNotValidateContents,
                         scontentlist);
       }
       else
       {
          addWsdlSchemas(wsdlFileName,
                         (DefinitionsDocument)wsdlDoc,
                         errorListener,
                         doNotValidateContents,
                         scontentlist);
       }
       
       DefinitionsDocument doc = (DefinitionsDocument) wsdlDoc;
       XmlObject[] typesArray = doc.getDefinitions().getTypesArray();
       Node domNode = wsdlDoc.getDomNode();
       NodeList childNodes = domNode.getChildNodes();
       scontentlist.size();
       
       
       
       
    }
    catch (XmlException e) {
      e.printStackTrace();
      
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    
  }
  private static void addWsdlSchemas(String wsdlFileName,
      DefinitionsDocument definitionsDocument,
      XmlErrorWatcher errorListener,
      boolean doNotValidateContents,
      ArrayList scontentlist)
  {
    XmlOptions opts = new XmlOptions().setErrorListener(errorListener);
    if (doNotValidateContents)
    {
      opts.setValidateTreatLaxAsSkip();
    }

    XmlObject[] types =
      definitionsDocument.getDefinitions().getTypesArray();

    for (int j = 0; j < types.length; j++)
    {
      XmlObject[] schemas =
        types[j].selectPath("declare namespace"
            + " xs=\"http://www.w3.org/2001/XMLSchema\""
            + " xs:schema");
      if (schemas.length == 0)
      {
        StscState.addWarning(errorListener,
            "The WSDL " + wsdlFileName
            + " has no schema documents in namespace "
            + "'http://www.w3.org/2001/XMLSchema'",
            XmlErrorCodes.GENERIC_ERROR,
            definitionsDocument);
        continue;
      }

      for (int k = 0; k < schemas.length; k++)
      {
        if (schemas[k] instanceof SchemaDocument.Schema)
        {
          SchemaDocumentImpl.SchemaImpl schemaImpl =
            (SchemaDocumentImpl.SchemaImpl)schemas[k];

          System.out.println("Validating schema...");
          if (schemaImpl.validate(opts))
          {
            System.out.println("Schema passed validation");
            scontentlist.add(schemas[k]);
          }
          else
          {
            System.out.println("Schema failed validation");
            scontentlist.add(schemas[k]);
          }
        }
      }
    }
  }

}
